using System.Collections;
using System.Data;
using System.Reflection;
using Agile.Common.UI;

namespace Agile.Common
{
    /// <summary>
    /// Wraps the CollectionBase class and adds some common functionality for collections.
    /// </summary>
    public abstract class AgileCollection : CollectionBase
    {
        #region Constants

        /// <summary>
        /// Format for displaying doubles
        /// </summary>
        private const string DOUBLE_FORMATTER = "$0.00";

        #endregion Constants

        /// <summary>
        /// Returns true if there are no items in the collection.
        /// </summary>
        public bool IsEmpty
        {
            get { return List.Count == 0; }
        }

        /// <summary>
        /// Check if the object is in the collection.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(object item)
        {
            return InnerList.Contains(item);
        }

        /// <summary>
        /// Gets the collection in a datatable ready for display (e.g. in a grid).
        /// </summary>
        /// <param name="propertyNames">The properties (columns) to include in the datatable.
        /// These must match the property name exactly EXCEPT the name MAY include spaces.</param>
        /// <returns></returns>
        public DataTable GetForDisplay(params string[] propertyNames)
        {
            if (Count == 0)
            {
                return null;
            }

            var displayValues = new DataTable("DataForAGrid");

            // Create the table columns
            foreach (string property in propertyNames)
                displayValues.Columns.Add(property);

            // Add a row for each item in the collection
            for (int i = 0; i < Count; i++)
            {
                DataRow newRow = displayValues.NewRow();
                object item = InnerList[i];

                foreach (string columnName in propertyNames)
                {
                    // Removed spaces from the string
                    string property = Strings.RemoveSpacesFromString(columnName);

                    // Get the value of the property,.
                    PropertyInfo propertyInfo = item.GetType().GetProperty(property);
                    object propertyValue = propertyInfo.GetValue(item, null);
                    if (propertyInfo.PropertyType.IsValueType
                        || propertyInfo.PropertyType.Name == "String")
                    {
                        //						if( propertyInfo.PropertyType == typeof( DateTime ) )
                        //						{
                        //							// TODO: simply storing as AUS - not generic
                        //							newRow[columnName] = ( ( DateTime ) propertyValue ) == DateTime.MinValue ?
                        //								string.Empty : ( ( DateTime ) propertyValue ).ToString(
                        //								DATE_FORMAT, Cult.DateTimeFormat );
                        //						}
                        if (propertyInfo.PropertyType == typeof (double))
                        {
                            newRow[columnName] = ((double) propertyValue).ToString(DOUBLE_FORMATTER);
                        }
                        else
                        {
                            newRow[columnName] = propertyValue.ToString();
                        }
                    }
                    else
                    {
                        var field = (IAgileControlDetails) propertyValue;
                        newRow[columnName] = field.DisplayValue;
                    }
                }
                displayValues.Rows.Add(newRow);
            }
            return displayValues;
        }


        /// <summary>
        /// Sort the items in the collection.
        /// </summary>
        /// <remarks>WARNING: The collection must be a collection of objects
        /// that implement the IAgileControlDetails interface.</remarks>
        public void Sort()
        {
            InnerList.Sort(AgileControlSorter.Build());
        }

        /// <summary>
        /// Sort the items in the collection
        /// </summary>
        /// <remarks>WARNING: The collection must be a collection of objects
        /// that implement the IAgileControlDetails interface.</remarks>
        public void SortReverse()
        {
            InnerList.Sort(AgileControlReverseSorter.Build());
        }
    }
}